The goal of this article is to configure Traefik proxy and HTTPS. See #7768 for reference.
Traefik 3.6.4 introduced a breaking change regarding
how percent-encoded characters are handled in URLs. Trilium puts the title
of an image or attachment in its URL path, so one whose title contains # or / is
requested at a path such as /api/images/…/diagram%231.png.
Traefik rejects these paths with HTTP 400, and the image does not load.
Search is not affected, because it sends its text in a query parameter.
The easiest solution is to update to Traefik 3.6.7 or later which reverts this configuration change. Alternatively, the configuration can be changed according to the section below.
To solve this, the Traefik static configuration must be modified in order to allow those characters:
entryPoints:
web:
http:
encodedCharacters:
allowEncodedSlash: true
allowEncodedHash: true
Setting up Traefik as reverse proxy requires setting the following labels:
labels:
- traefik.enable=true
- traefik.http.routers.trilium.entrypoints=https
- traefik.http.routers.trilium.rule=Host(`trilium.mydomain.tld`)
- traefik.http.routers.trilium.tls=true
- traefik.http.routers.trilium.service=trilium
- traefik.http.services.trilium.loadbalancer.server.port=8080
# scheme must be HTTP instead of the usual HTTPS because Trilium listens on HTTP internally
- traefik.http.services.trilium.loadbalancer.server.scheme=http
- traefik.docker.network=proxy
# forward HTTP to HTTPS
- traefik.http.routers.trilium.middlewares=trilium-headers@docker
- traefik.http.middlewares.trilium-headers.headers.customrequestheaders.X-Forwarded-Proto=https
After setting up a reverse proxy, make sure to configure the Trusted proxy.
docker-compose.yamlservices:
trilium:
image: triliumnext/trilium
container_name: trilium
networks:
- traefik-proxy
environment:
- TRILIUM_NETWORK_TRUSTEDREVERSEPROXY=my-traefik-host-ip # e.g., 172.18.0.0/16
volumes:
- /path/to/data:/home/node/trilium-data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
labels:
- traefik.enable=true
- traefik.http.routers.trilium.entrypoints=https
- traefik.http.routers.trilium.rule=Host(`trilium.mydomain.tld`)
- traefik.http.routers.trilium.tls=true
- traefik.http.routers.trilium.service=trilium
- traefik.http.services.trilium.loadbalancer.server.port=8080
# scheme must be HTTP instead of the usual HTTPS because of how trilium works
- traefik.http.services.trilium.loadbalancer.server.scheme=http
- traefik.docker.network=traefik-proxy
# Tell Trilium the original request was HTTPS
- traefik.http.routers.trilium.middlewares=trilium-headers@docker
- traefik.http.middlewares.trilium-headers.headers.customrequestheaders.X-Forwarded-Proto=https
networks:
traefik-proxy:
external: true